package com.tianquan.log;/**
 * @author starsea
 * @date 2024-10-16 上午11:27
 */

import com.tianquan.mapper.LogMapper;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @BelongsProject: uploaddemo
 * @BelongsPackage: com.tianquan.log
 * @Author: tianquan
 * @CreateTime: 2024-10-16  11:27
 * @Description: 测试
 * @Version: 1.0
 */

@Component
public class Task {

    @Autowired
    private LogMapper logMapper;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private LocalLogService localLogService;

    public static final Lock LOCK = new ReentrantLock(true);

    public static List<Log> list = new ArrayList<>(1024);

    public static List<Log> list1 = new ArrayList<>(1024);

    public static ExecutorService executorService = Executors.newFixedThreadPool(5);

    @Scheduled(cron = " 0/5 * * * * ? ")
    public void run() {
        LOCK.lock();
        List<Log> newList = new ArrayList<>(list);
        // 没有日志就不添加
        if (newList.isEmpty()) {
            LOCK.unlock();
            return;
        }
        // 清空list
        clearList();
        LOCK.unlock();
        // 将数据入库
        executorService.submit(new Thread(new InsertLogTask(newList, logMapper, redissonClient, localLogService)));
        // 清空list1
        list1.clear();
    }

    private void clearList() {
        List<Log> temp = list;
        list = list1;
        list1 = temp;
    }

    static class InsertLogTask implements Runnable {

        private final List<Log> list;

        private LogMapper logMapper;

        private RedissonClient redissonClient;

        private LocalLogService localLogService;

        public InsertLogTask(List<Log> list, LogMapper logMapper, RedissonClient redissonClient, LocalLogService localLogService) {
            this.list = list;
            this.logMapper = logMapper;
            this.redissonClient = redissonClient;
            this.localLogService = localLogService;
        }

        @Override
        public void run() {
             // 需要写入的次数
            int count = (list.size() / 127) + 1;
            int size = list.size();

            List<Log> logs = new ArrayList<>(128);
            for (int i = 0; count > 0; size -= 127, i += 127, count--) {
                try {
                    if (count == 1) {
                        int endIndex = Math.min(i + size, this.list.size());
                        logs.addAll(this.list.subList(i, endIndex));
                        logMapper.batchInsert(logs);
                    } else {
                        int endIndex = Math.min(i + 127, this.list.size());
                        logs.addAll(this.list.subList(i, endIndex));
                        logMapper.batchInsert(logs);
                    }
                    logs.clear();
                } catch (Exception e) {
                    handleDatabaseFailure(logs, e);
                    logs.clear();
                }
            }
        }

        private void handleDatabaseFailure(List<Log> logs, Exception e) {
            // 1.发送 "数据库出现异常信息" 邮件给管理员
            // sendEmailAdmin();
            // 2.将数据保存到redis
            Log log = new Log(null, null, Level.ERROR.getValue(),
                    "localhost", "redis", null, e.toString(), new Date());
            logs.add(log);
            try {
                redissonClient.getList("errorLog").addAll(logs);
            } catch (Exception ex) {
                // 1. 发送 "Redis出现异常信息" 邮件给管理员
                // sendEmailAdmin();
                // 2. Redis保存失败 保存到本地
                localLogService.LocalPersistence(logs);
            }
        }

    }
}